<template><div><h2 id="csrf-保护" tabindex="-1"><a class="header-anchor" href="#csrf-保护"><span>CSRF 保护</span></a></h2>
<p>Laravel 5.5 中文文档 /</p>
<p>本文档最新版为 <a href="https://learnku.com/docs/laravel/10.x" target="_blank" rel="noopener noreferrer">10.x</a>，旧版本可能放弃维护，推荐阅读最新版！</p>
<h2 id="laravel-下的伪造跨站请求保护-csrf" tabindex="-1"><a class="header-anchor" href="#laravel-下的伪造跨站请求保护-csrf"><span>Laravel 下的伪造跨站请求保护 CSRF</span></a></h2>
<ul>
<li><a href="#csrf-introduction">简介</a></li>
<li><a href="#csrf-excluding-uris">CSRF 白名单</a></li>
<li><a href="#csrf-x-csrf-token">X-CSRF-Token</a></li>
<li><a href="#csrf-x-xsrf-token">X-XSRF-Token</a></li>
</ul>
<h2 id="简介" tabindex="-1"><a class="header-anchor" href="#简介"><span>简介</span></a></h2>
<p>Laravel 可以轻松地保护应用程序免受 <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery" target="_blank" rel="noopener noreferrer">跨站请求伪造</a> (CSRF) 的攻击。跨站请求伪造是一种恶意的攻击，它凭借已通过身份验证的用户身份来运行未经过授权的命令。</p>
<p>Laravel 会自动为每个活跃用户的会话生成一个 CSRF「令牌」。该令牌用于验证经过身份验证的用户是否是向应用程序发出请求的用户。</p>
<p>任何情况下当你在应用程序中定义 HTML 表单时，都应该在表单中包含一个隐藏的 CSRF 令牌字段，以便 CSRF 保护中间件可以验证该请求。可以使用辅助函数 <code v-pre>csrf_field</code> 来生成令牌字段：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">&lt;</span>form method<span class="token operator">=</span><span class="token string double-quoted-string">"POST"</span> action<span class="token operator">=</span><span class="token string double-quoted-string">"/profile"</span><span class="token operator">></span></span>
<span class="line">    <span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token function">csrf_field</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span></span>
<span class="line">    <span class="token operator">...</span></span>
<span class="line"><span class="token operator">&lt;</span><span class="token operator">/</span>form<span class="token operator">></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>包含在 <code v-pre>web</code> 中间件组里的 <code v-pre>VerifyCsrfToken</code> <a href="https://learnku.com/docs/laravel/5.5/middleware" target="_blank" rel="noopener noreferrer">中间件</a>会自动验证请求里的令牌是否与存储在会话中令牌匹配。</p>
<h4 id="csrf-令牌-javascript" tabindex="-1"><a class="header-anchor" href="#csrf-令牌-javascript"><span>CSRF 令牌 &amp; JavaScript</span></a></h4>
<p>构建由 Javascript 驱动的应用时，可以很方便地让 Javascript HTTP 函数库在发起每一个请求时自动附上 CSRF 令牌。默认情况下， <code v-pre>resources/assets/js/bootstrap.js</code> 文件会用 Axios HTTP 函数库注册的 <code v-pre>csrf-token</code> meta 标签中的值。如果你不使用这个函数库，你需要手动为你的应用配置此行为。</p>
<h2 id="csrf-白名单" tabindex="-1"><a class="header-anchor" href="#csrf-白名单"><span>CSRF 白名单</span></a></h2>
<p>有时候你可能希望设置一组并不需要 CSRF 保护的 URI。例如，如果你正在使用 <a href="https://stripe.com/" target="_blank" rel="noopener noreferrer">Stripe</a> 处理付款并使用了他们的 webhook 系统，你会需要从 CSRF 的保护中排除 Stripe Webhook 处理程序路由，因为 Stripe 并不会给你的路由发送 CSRF 令牌。</p>
<p>你可以把这类路由放到 <code v-pre>routes/web.php</code> 外，因为 <code v-pre>RouteServiceProvider</code> 的 <code v-pre>web</code> 中间件适用于该文件中的所有路由。不过，你也可以通过将这类 URI 添加到 <code v-pre>VerifyCsrfToken</code> 中间件中的 <code v-pre>$except</code> 属性来排除对这类路由的 CSRF 保护：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Foundation<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Middleware<span class="token punctuation">\</span>VerifyCsrfToken</span> <span class="token keyword">as</span> BaseVerifier<span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">VerifyCsrfToken</span> <span class="token keyword">extends</span> <span class="token class-name">BaseVerifier</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 这些 URI 将免受 CSRF 验证</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">protected</span> <span class="token variable">$except</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'stripe/*'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="x-csrf-token" tabindex="-1"><a class="header-anchor" href="#x-csrf-token"><span>X-CSRF-TOKEN</span></a></h2>
<p>除了检查 POST 参数中的 CSRF 令牌外，<code v-pre>VerifyCsrfToken</code> 中间件还会检查 <code v-pre>X-CSRF-TOKEN</code> 请求头。你可以将令牌保存在 HTML <code v-pre>meta</code> 标签中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">&lt;</span>meta name<span class="token operator">=</span><span class="token string double-quoted-string">"csrf-token"</span> content<span class="token operator">=</span><span class="token string double-quoted-string">"{{ csrf_token() }}"</span><span class="token operator">></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>然后你就可以使用类似 jQuery 的库自动将令牌添加到所有请求的头信息中。这可以为基于 AJAX 的应用提供简单、方便的 CSRF 保护：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line">$<span class="token operator">.</span><span class="token function">ajaxSetup</span><span class="token punctuation">(</span><span class="token punctuation">{</span></span>
<span class="line">    headers<span class="token punctuation">:</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token string single-quoted-string">'X-CSRF-TOKEN'</span><span class="token punctuation">:</span> $<span class="token punctuation">(</span><span class="token string single-quoted-string">'meta[name="csrf-token"]'</span><span class="token punctuation">)</span><span class="token operator">.</span><span class="token function">attr</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'content'</span><span class="token punctuation">)</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p>{tip} 默认情况下， <code v-pre>resources/assets/js/bootstrap.js</code> 文件会用 Axios HTTP 函数库注册 <code v-pre>csrf-token</code> meta 标签中的值。如果你不使用这个函数库，则需要为你的应用手动配置此行为。</p>
</blockquote>
<h2 id="x-xsrf-token" tabindex="-1"><a class="header-anchor" href="#x-xsrf-token"><span>X-XSRF-TOKEN</span></a></h2>
<p>Laravel 将当前的 CSRF 令牌存储在由框架生成的每个响应中包含的一个 <code v-pre>XSRF-TOKEN</code> cookie 中。为方便起见，你可以使用 cookie 值来设置 X-XSRF-TOKEN 请求头，而一些 JavaScript 框架和库（如 Angular 和 Axios）会自动将这个值添加到 <code v-pre>X-XSRF-TOKEN</code> 头中。</p>
<h2 id="译者署名" tabindex="-1"><a class="header-anchor" href="#译者署名"><span>译者署名</span></a></h2>
<table>
<thead>
<tr>
<th>用户名</th>
<th>头像</th>
<th>职能</th>
<th>签名</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="http://weibo.com/wangkaibo" target="_blank" rel="noopener noreferrer">@王凯波</a></td>
<td><img src="https://cdn.learnku.com/uploads/avatars/1924_1487053084.jpeg?imageView2/1/w/100/h/100" alt="100"></td>
<td>翻译</td>
<td>面向工资编程 <a href="https://github.com/wangkaibo/" target="_blank" rel="noopener noreferrer">@wangkaibo</a></td>
</tr>
<tr>
<td><a href="https://learnku.com/users/16370" target="_blank" rel="noopener noreferrer">@Lichmaker</a></td>
<td><img src="https://cdn.learnku.com/uploads/avatars/16370_1499995124.jpg?imageView2/1/w/100/h/100" alt="100"></td>
<td>翻译</td>
<td>Happy Coding! 😃 我的微博：<a href="http://weibo.com/1779555595/" target="_blank" rel="noopener noreferrer">神经考拉君</a></td>
</tr>
<tr>
<td><a href="https://learnku.com/users/5350" target="_blank" rel="noopener noreferrer">@JokerLinly</a></td>
<td><img src="https://cdn.learnku.com/uploads/avatars/5350_1481857380.jpg" alt="5350_1481857380.jpg"></td>
<td>Review</td>
<td>Stay Hungry. Stay Foolish.</td>
</tr>
</tbody>
</table>
<hr>
<blockquote>
<p>{note} 欢迎任何形式的转载，但请务必注明出处，尊重他人劳动共创开源社区。</p>
<p>转载请注明：本文档由 Laravel China 社区 <a href="https://laravel-china.org/" target="_blank" rel="noopener noreferrer">laravel-china.org</a> 组织翻译，详见 <a href="https://learnku.com/laravel/t/5756/laravel-55-document-translation-call-come-and-join-the-translation" target="_blank" rel="noopener noreferrer">翻译召集帖</a>。</p>
<p>文档永久地址： <a href="https://learnku.com/docs/laravel" target="_blank" rel="noopener noreferrer">《Laravel 中文文档》</a></p>
</blockquote>
</div></template>


